#include "im4c.h"
#include "stdlib.h"
#include "hex.h"
#include "protocol.h"
#include <esp_log.h>
#include <esp_system.h>

extern char gl_szUserAgent[];
ImMesTaskHandle_t gl_mes_task_array[128] = {0};
int gl_mes_task_array_count = 0;

#define TAG "im4c"

void onConnStaChange(int sta){
}

void onLoginSucc(char* szUserName,int nUserNameLen,char *szUserAgent,int nUserAgentLen,char *szUid,int nUid,char *szSid,int nSid,char *szAccessToken,int nAccessToken,char *szWebCtxPath, int nWebCtxPath){
	
}


void onLoginFail(char* szUserName,int nUserNameLen){
}


void onLogouSucc(char* szUserName, int len) {
}

void onLogouFail(char* szUserName, int len) {
}

void onLoginSta(char* szUserReason,int len){
}

void onNetworkSta(int sta){
	// int * p_sta = NULL;
	// MallocBuf(int,p_sta,sizeof(int));
	// memcpy(p_sta,&sta,sizeof(int));
}



void onRecvHeartBeat(){
}


int sendImEventMsg(char *szRtJson, int *nRtJsonLen,int channelID,char *src_uid,char *dst_uid,char *evt_name,char *evt_key,char *evt_obj){
#ifdef WIN32
    int totalLen = 0;
#endif
	char *_szSCMDA = NULL;
	char _szSCM[] = "ImEventProxy";
	int nRet = 0;
	cJSON *pRoot = NULL;
	char *jsonSTR = NULL;
	Approxy4cST_t *approxy4cST = NULL;
	long long tm = fn_GetSystemTime();
	char *tmpSRC_UID = NULL;
	approxy4cST = FindApproxy4cSTByChannelID(channelID);

	if(src_uid && strlen(src_uid) > 0){
		//fn_RYN_LOG_DEBUG("1");
		MallocBuf(char,tmpSRC_UID,strlen(src_uid) + 1);
		memcpy(tmpSRC_UID,src_uid,strlen(src_uid));
	}else{
		//fn_RYN_LOG_DEBUG("2 %d",strlen(gl_sidSTR));
		MallocBuf(char,tmpSRC_UID,strlen(approxy4cST->gl_sidSTR) + 1);
		memcpy(tmpSRC_UID,approxy4cST->gl_sidSTR,strlen(approxy4cST->gl_sidSTR));
	}
		//fn_RYN_LOG_DEBUG("3");

	pRoot = fn_cJSON_CreateObject();
	fn_cJSON_AddStringToObject(pRoot,"src_uag",gl_szUserAgent);
	fn_cJSON_AddStringToObject(pRoot,"src_uid",tmpSRC_UID);
	fn_cJSON_AddStringToObject(pRoot,"dst_uid",dst_uid);
	fn_cJSON_AddStringToObject(pRoot,"evt_name",evt_name);
	fn_cJSON_AddStringToObject(pRoot,"evt_key",evt_key);
	fn_cJSON_AddStringToObject(pRoot,"evt_obj",evt_obj);
	fn_cJSON_AddNumberToObject(pRoot,"tm",tm);

	jsonSTR = fn_cJSON_PrintUnformatted(pRoot);

	//sprintf_s(_szSCMDA,totalLen,"src_uid=%s&dst_uid=%s&evt_name=%s&evt_key=%s&evt_obj=%s&tm=%lld",src_uid,dst_uid,evt_name,evt_key,evt_obj,tm);
	//fn_RYN_LOG_DEBUG("sendImEventMsg _szSCMDA = [%s]",jsonSTR);
    if(1){
        MallocBuf(char,_szSCMDA,strlen(jsonSTR) + 1);
        memcpy_s(_szSCMDA,strlen(jsonSTR),jsonSTR,strlen(jsonSTR));
    }

#ifdef WIN32
	if(0){
		char *_tmp = NULL;
		MallocBuf(char,_tmp,totalLen * 3);
		fn_Ansii_to_Utf8(jsonSTR,&_tmp);
		MallocBuf(char,_szSCMDA,totalLen * 3);
		memset(_szSCMDA,0,totalLen * 3);
		memcpy_s(_szSCMDA,totalLen * 3,_tmp,totalLen * 3);
		FreeBuf(_tmp);
	}
#endif
	//fn_RYN_LOG_DEBUG("_szSCMDA:%s",_szSCMDA);

	nRet = SendSacSCMPackageToBeat(szRtJson,nRtJsonLen,approxy4cST,_szSCM,_szSCMDA);
	fn_RYN_LOG_DEBUG(TAG,"sendImEventMsg szRtJson = [%s]",szRtJson);

	fn_cJSON_Delete(pRoot);
	FreeBuf(tmpSRC_UID);
	FreeBuf(jsonSTR);
	FreeMem(_szSCMDA);
	return nRet;
}

/** 发送视频呼叫请求 **/
int sendCallin(char *szRtJson, int *nLen,char *dst_uid,ImCallVA_t *im){
	int nRet = 0;
	cJSON *pRoot = NULL;
	char *evt_obj = NULL;

	pRoot = fn_cJSON_CreateObject();
	fn_cJSON_AddStringToObject(pRoot,"dst_ip",im->dst_ip);
	fn_cJSON_AddNumberToObject(pRoot,"dst_port",im->dst_port);
	fn_cJSON_AddNumberToObject(pRoot,"callType",im->callType);
	fn_cJSON_AddStringToObject(pRoot,"callid",im->callid);
	fn_cJSON_AddNumberToObject(pRoot,"uid",im->uid);
	fn_cJSON_AddNumberToObject(pRoot,"uid_ex",im->uid_ex);
	evt_obj = fn_cJSON_PrintUnformatted(pRoot);
	nRet = sendImEventMsg(szRtJson,nLen,CHANNEL_BEGIN,NULL,dst_uid,"im_CallinVA","",evt_obj);
	fn_cJSON_Delete(pRoot);
	return nRet;
}
/** 发送视频呼叫接收请求 **/
int sendAccept(char *szRtJson, int *nLen,char *dst_uid,ImCallVA_t *im){
	int nRet = 0;
	cJSON *pRoot = NULL;
	char *evt_obj = NULL;
	pRoot = fn_cJSON_CreateObject();
	fn_cJSON_AddStringToObject(pRoot,"dst_ip",im->dst_ip);
	fn_cJSON_AddNumberToObject(pRoot,"dst_port",im->dst_port);
	fn_cJSON_AddNumberToObject(pRoot,"callType",im->callType);
	fn_cJSON_AddStringToObject(pRoot,"callid",im->callid);
	fn_cJSON_AddNumberToObject(pRoot,"uid",im->uid);
	fn_cJSON_AddNumberToObject(pRoot,"uid_ex",im->uid_ex);
	evt_obj = fn_cJSON_PrintUnformatted(pRoot);
	nRet = sendImEventMsg(szRtJson,nLen,CHANNEL_BEGIN,NULL,dst_uid,"im_AcceptVA","",evt_obj);
	fn_cJSON_Delete(pRoot);
	return 0;
}
/** 发送视频呼叫拒绝请求 **/
int sendReject(char *szRtJson, int *nLen,char *dst_uid,ImCallVA_t *im){
	int nRet = 0;
	cJSON *pRoot = NULL;
	char *evt_obj = NULL;
	pRoot = fn_cJSON_CreateObject();
	fn_cJSON_AddStringToObject(pRoot,"dst_ip",im->dst_ip);
	fn_cJSON_AddNumberToObject(pRoot,"dst_port",im->dst_port);
	fn_cJSON_AddNumberToObject(pRoot,"callType",im->callType);
	fn_cJSON_AddStringToObject(pRoot,"callid",im->callid);
	fn_cJSON_AddNumberToObject(pRoot,"uid",im->uid);
	fn_cJSON_AddNumberToObject(pRoot,"uid_ex",im->uid_ex);
	evt_obj = fn_cJSON_PrintUnformatted(pRoot);
	nRet = sendImEventMsg(szRtJson,nLen,CHANNEL_BEGIN,NULL,dst_uid,"im_RejectVA","",evt_obj);
	fn_cJSON_Delete(pRoot);
	return 0;
}
/** 发送视频通话结束请求 **/
int sendComplete(char *szRtJson, int *nLen,char *dst_uid,ImCallVA_t *im){
	int nRet = 0;
	cJSON *pRoot = NULL;
	char *evt_obj = NULL;
	pRoot = fn_cJSON_CreateObject();
	fn_cJSON_AddStringToObject(pRoot,"dst_ip",im->dst_ip);
	fn_cJSON_AddNumberToObject(pRoot,"dst_port",im->dst_port);
	fn_cJSON_AddNumberToObject(pRoot,"callType",im->callType);
	fn_cJSON_AddStringToObject(pRoot,"callid",im->callid);
	fn_cJSON_AddNumberToObject(pRoot,"uid",im->uid);
	fn_cJSON_AddNumberToObject(pRoot,"uid_ex",im->uid_ex);
	evt_obj = fn_cJSON_PrintUnformatted(pRoot);
	nRet = sendImEventMsg(szRtJson,nLen,CHANNEL_BEGIN,NULL,dst_uid,"im_CompleteVA","",evt_obj);
	fn_cJSON_Delete(pRoot);
	return 0;
}

int sendMesProxyTaskResult(int channelID, char *task_id,int isSucc, char *result){
	char *jsonSTR = NULL;
	int nRet = 0;
	char *rtJson = NULL;
	int nRtJsonLen = 0;
	char *gl_uidSTR = NULL;
	int len = 0;
	cJSON *pRoot = fn_cJSON_CreateObject();
	MallocBuf(char,rtJson,1024);
	MallocBuf(char,gl_uidSTR,48);
	
	fn_cJSON_AddStringToObject(pRoot,"task_id",task_id);
	fn_cJSON_AddNumberToObject(pRoot,"status",isSucc == 1?1:0);
	if(result)
	fn_cJSON_AddStringToObject(pRoot,"result",result);
	jsonSTR = fn_cJSON_PrintUnformatted(pRoot);
	//fn_RYN_LOG_DEBUG("json: %s",jsonSTR);
	//fn_RYN_LOG_DEBUG("im_MesProxyTask: %d",im->channelID);
	GetUidSTR(gl_uidSTR, &len);
	nRet = sendImEventMsg(rtJson,&nRtJsonLen,channelID,gl_uidSTR,gl_uidSTR,"im_MesProxyTaskResult","",jsonSTR);
	fn_cJSON_Delete(pRoot);
	FreeMem(gl_uidSTR);
	FreeMem(rtJson);
	return 0;
}


int MesTaskSDK_Sql(MesTaskResult_t *result_out,IMEventST_t *im,cJSON *cjson){
	char *sql = fn_cJSON_GetValueString(cjson,"sql");
	fn_RYN_LOG_DEBUG(TAG,"sql: %s",sql);
	return 0;
}

ImMesTaskHandle_t mes_task_array[] = {
	{"Sql0",&MesTaskSDK_Sql},
	{"NULL",NULL}
};

int im_MesTask_addHandle(ImMesTaskHandle_t handle){
	gl_mes_task_array[gl_mes_task_array_count++] = handle;
	return 0;
}

// 带回调的消息代理转发
void im_MesProxyTask(IMEventST_t * im)
{
	int match = 0;
	int i = 0;
	cJSON *cjson = fn_cJSON_Parse(im->szEventObj);
	if(!cjson){
		fn_RYN_LOG_ERROR(TAG,"parse im_MesProxy_MesTask ERR! evtObjSTR:[%s]",im->szEventObj);
		return ;
	}
	if(gl_mes_task_array_count == 0){
		for(i = 0;i<sizeof(gl_mes_task_array)/sizeof(ImMesTaskHandle_t);i++){
			memset(gl_mes_task_array[i].task_cmd,0,sizeof(gl_mes_task_array[i].task_cmd));
			gl_mes_task_array[i].taskFunctionCall = NULL;
		}
		for(i = 0;i<sizeof(gl_mes_task_array)/sizeof(ImMesTaskHandle_t);i++){
			gl_mes_task_array[gl_mes_task_array_count] = mes_task_array[i];
			gl_mes_task_array_count++;
		}
	}
	
	fn_RYN_LOG_INFO(TAG,"MesTask .. %s, %s",im->szEventKey, im->szEventObj);
	fn_RYN_LOG_INFO(TAG,"可用内存：%.2f kb",(float)esp_get_free_heap_size()/1024);

	if(1){
		char *script_name = fn_cJSON_GetValueString(cjson,"script_name");
		for(i = 0;i<sizeof(gl_mes_task_array)/sizeof(ImMesTaskHandle_t);i++){
			if(script_name && EquSTR(gl_mes_task_array[i].task_cmd,script_name) && gl_mes_task_array[i].taskFunctionCall){
				MesTaskResult_t *result = NULL;
				MallocMem(MesTaskResult_t,result);
				memset(result->errorMsg,0,sizeof(result->errorMsg));
				gl_mes_task_array[i].taskFunctionCall(result,im,cjson);
				if(result && result->result && result->result_len > 0 && result->errorCode == 1000){
					// 模拟任务执行完成 发送一个回调请求 必须包含task_id
					sendMesProxyTaskResult(im->channelID,im->szEventKey,1,result->result);//success: 1 , failed: 0
				}else{
					sendMesProxyTaskResult(im->channelID,im->szEventKey,0,strlen(result->errorMsg)?result->result:"Unknow Error!");//success: 1 , failed: 0
				}
				FreeBuf(result->result);
				FreeMem(result);
				match = 1;
			}
		}
	}

	fn_cJSON_Delete(cjson);

	if(match == 0){
		// 模拟任务执行完成 发送一个回调请求 必须包含task_id
		sendMesProxyTaskResult(im->channelID,im->szEventKey,0,"unSupport this mes_task handle!!");//success: 1 , failed: 0
	}
}

void im_MesProxy(IMEventST_t * im)
{
	char rtJson[2048] = {0};
	int nRtJsonLen = 0;
	char *dst_uid = NULL;
	char *dst_mSessionID = NULL;
	char *im_ctx = NULL;
	cJSON *cjson = fn_cJSON_Parse(im->szEventObj);
	if(!cjson){
		fn_RYN_LOG_ERROR(TAG,"parse im_MesProxy ERR! evtObjSTR:[%s]",im->szEventObj);
		return ;
	}
	dst_uid = fn_cJSON_GetObjectItem(cjson,"dst_uid") != NULL ? fn_cJSON_GetObjectItem(cjson,"dst_uid")->valuestring:"";
	dst_mSessionID = fn_cJSON_GetObjectItem(cjson,"dst_mSessionID") != NULL ? fn_cJSON_GetObjectItem(cjson,"dst_mSessionID")->valuestring:"";
	im_ctx = fn_cJSON_GetObjectItem(cjson,"im_ctx") != NULL ? fn_cJSON_GetObjectItem(cjson,"im_ctx")->valuestring:"";
	sendImText(rtJson,&nRtJsonLen,dst_uid,dst_mSessionID,im_ctx);
	fn_cJSON_Delete(cjson);
}

/** IM **/
void onRecvEvent(IMEventST_t *im0){
	//pthread_t p1;
	int releaseBufferInPtThread = 0;
	IMEventST_t *im = NULL;
	MallocMem(IMEventST_t,im);
	im->nEventKey = im0->nEventKey;
	im->nEventName = im0->nEventName;
	im->nEventObj = im0->nEventObj;
	im->nMsgID = im0->nMsgID;
	im->nMsgType = im0->nMsgType;
	im->nRecvTime = im0->nRecvTime;
	im->nSenderAgent = im0->nSenderAgent;
	im->nSenderAgentName = im0->nSenderAgentName;
	im->nSenderAgentAvatar = im0->nSenderAgentAvatar;

	MallocBuf(char,im->szEventKey,im->nEventKey+1);
	MallocBuf(char,im->szEventName,im->nEventName+1);
	MallocBuf(char,im->szEventObj,im->nEventObj+1);
	MallocBuf(char,im->szMsgID,im->nMsgID+1);
	MallocBuf(char,im->szRecvTime,im->nRecvTime+1);
	MallocBuf(char,im->szSenderAgent,im->nSenderAgent+1);
	MallocBuf(char,im->szSenderAgentName,im->nSenderAgentName+1);
	MallocBuf(char,im->szSenderAgentAvatar,im->nSenderAgentAvatar+1);

	memcpy_s(im->szEventKey,im0->nEventKey,im0->szEventKey,im0->nEventKey);
	memcpy_s(im->szEventName,im0->nEventName,im0->szEventName,im0->nEventName);
	memcpy_s(im->szEventObj,im0->nEventObj,im0->szEventObj,im0->nEventObj);
	memcpy_s(im->szMsgID,im0->nMsgID,im0->szMsgID,im0->nMsgID);
	memcpy_s(im->szRecvTime,im0->nRecvTime,im0->szRecvTime,im0->nRecvTime);
	memcpy_s(im->szSenderAgent,im0->nSenderAgent,im0->szSenderAgent,im0->nSenderAgent);
	memcpy_s(im->szSenderAgentName,im0->nSenderAgentName,im0->szSenderAgentName,im0->nSenderAgentName);
	memcpy_s(im->szSenderAgentAvatar,im0->nSenderAgentAvatar,im0->szSenderAgentAvatar,im0->nSenderAgentAvatar);

	im->channelID = im0->channelID;
	fn_RYN_LOG_INFO(TAG,"im->channelID: %d",im->channelID);
	if(im->szEventName){
		fn_RYN_LOG_INFO(TAG,"eventName:%s, eventKey:%s, eventObj:%s",im->szEventName,im->szEventKey,strlen(im->szEventObj)>500?"Too long..":im->szEventObj);
	}

	if(strcmp("im_MesProxyTask", im->szEventName) == 0){//消息代理转发
		int len = 0;
		if(im0->ncb_url){
			len = strlen(im0->ncb_url);
		}
		if(im0->ncb == 1 && len > 0){
			MallocBuf(char,im->ncb_url,len+1);
			memcpy_s(im->ncb_url,len,im0->ncb_url,len);
		}
		im_MesProxyTask(im);
		if(im0->ncb == 1 && len > 0){
			FreeBuf(im0->ncb_url);
		}
	}else if(strcmp("im_MeSWITCH",im->szEventName) == 0){//用于控制开关等命令
		if(strcmp("exit",im->szEventKey) == 0){
			esp_restart();
		}
	}

	if(!releaseBufferInPtThread){
		FreeBuf(im->szMsgID);
		FreeBuf(im->szSenderAgent);
		FreeBuf(im->szSenderAgentName);
		FreeBuf(im->szSenderAgentAvatar);
		FreeBuf(im->szRecvTime);
		FreeBuf(im->szEventName);
		FreeBuf(im->szEventKey);
		FreeBuf(im->szEventObj);
		FreeBuf(im);
	}

}

//#ifdef RYN_USE_THREADPOOL
//void IMHandle(void *arg) {
//#else
void IMHandle(void *arg) {
//#endif // RYN_USE_THREADPOOL
	cJSON *pRoot = NULL;
	//char * szRtJson = (char *)arg;
	IMHandleST_t *imHandleST = (IMHandleST_t *)arg;
	char *szRtJson = imHandleST->json;
	int nMsgType = 0;					/** 娑堟伅绫诲瀷 	**/
	char * szMsgID = NULL;				/** 娑堟伅ID 		**/
	char * szSenderAgent = NULL;		/** 鍙戦€佹柟ID	**/
	char * szRecvTime = NULL;			/** 鎺ユ敹鏃堕棿	**/
	char * szRecvierAgent = NULL;		/** 鎺ユ敹鏂笽D	**/
	int nTmpType = 1;
	int ncb = 0;						/** 0不需要回调 1需要回调	**/
	char *ncb_url = NULL;				/** 回调的http URL地址		**/

	// char * szText = NULL;
	// char * szLocX = NULL;
	// char * szLocY = NULL;
	// char * szLabel = NULL;
	// char * szMediaID = NULL;
	char * szEventKey = NULL;
	char * szEventName = NULL;
	char * szEventObj = NULL;
	// char * szTakeTime = NULL;

	IMEventST_t *pevt = NULL;
	IMTextST_t *ptext = NULL;
	IMLocationST_t *ploc = NULL;
	IMMediaST_t *pmedia = NULL;
	if(strlen(szRtJson) <=0 ) {
		FreeBuf(szRtJson);
		FreeMem(imHandleST);
		return ;
	}

	/** IM **/
	pRoot = fn_cJSON_Parse(szRtJson);
	nMsgType = fn_cJSON_GetObjectItem(pRoot,"nMsgType")->valueint;
	szMsgID = fn_cJSON_GetObjectItem(pRoot,"szMsgID")->valuestring;
	szSenderAgent = fn_cJSON_GetObjectItem(pRoot,"szSenderAgent")->valuestring;
	szRecvTime = fn_cJSON_GetObjectItem(pRoot,"szRecvTime")->valuestring;
	szRecvierAgent = fn_cJSON_GetObjectItem(pRoot,"szRecvierAgent")->valuestring;

	// text
	nTmpType = nMsgType % 10;
	fn_RYN_LOG_DEBUG(TAG,"IM Recv nMsgType:%d,nTmpType:%d",nMsgType,nTmpType);
	switch(nTmpType){
	case 0://event
		//szEventName =  fn_cJSON_GetObjectItem(pRoot,"eventName")->valuestring;
		//szEventKey =  fn_cJSON_GetObjectItem(pRoot,"eventKey")->valuestring;
		//szEventObj =  fn_cJSON_GetObjectItem(pRoot,"eventObj")->valuestring;

		szEventName = fn_cJSON_GetValueString(pRoot,"eventName");
		szEventKey = fn_cJSON_GetValueString(pRoot,"eventKey");
		szEventObj = fn_cJSON_GetValueString(pRoot,"eventObj");

		if(szEventName){
			MallocMem(IMEventST_t,pevt);
			pevt->channelID = imHandleST->channelID;
			pevt->nMsgType = nMsgType;
			pevt->szMsgID = szMsgID;
			pevt->szSenderAgent = szSenderAgent;
			pevt->szRecvierAgent = szRecvierAgent;
			pevt->szRecvTime = szRecvTime;
			pevt->szEventName = szEventName;
			pevt->szEventKey = szEventKey;
			pevt->szEventObj = szEventObj;
		
			pevt->nMsgID = strlen(szMsgID != NULL ? szMsgID : "");
			pevt->nSenderAgent = strlen(szSenderAgent != NULL ? szSenderAgent : "");
			pevt->nRecvierAgent = strlen(szRecvierAgent != NULL ? szRecvierAgent : "");
			pevt->nRecvTime = strlen(szRecvTime != NULL ? szRecvTime : "");
			pevt->nEventName = strlen(szEventName != NULL ? szEventName : "");
			pevt->nEventKey = strlen(szEventKey != NULL ? szEventKey : "");
			pevt->nEventObj = strlen(szEventObj != NULL ? szEventObj : "");
		
			ncb = fn_cJSON_GetObjectItem(pRoot,"ncb")?fn_cJSON_GetObjectItem(pRoot,"ncb")->valueint:0;
			pevt->ncb = ncb;
			if(ncb == 1){
				ncb_url = fn_cJSON_GetObjectItem(pRoot,"ncb_url")?fn_cJSON_GetObjectItem(pRoot,"ncb_url")->valuestring:NULL;
				pevt->ncb_url = ncb_url;
			}
			onRecvEvent(pevt);
		}
		break;
	
	default:
		fn_RYN_LOG_DEBUG(TAG,"switch default:nTmpType = %d",nTmpType);
		break;
	}

	fn_cJSON_Delete(pRoot);

	FreeBuf(pevt);
	FreeBuf(ptext);
	FreeBuf(ploc);
	FreeBuf(pmedia);

	FreeBuf(szRtJson);
	FreeMem(imHandleST);
}